
package iks.render.anim
{
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import iks.event.*;
	import iks.iface.*;
	import iks.utils.*;
	
	/**
	 * 动画类, 装载 KBitmapAnimator 对象, 实现动画功能, 同时支持定位点的调整, 必须手动释放其资源.
	 * 对于手动释放 KSpriteAnimator 对象的规则, 首先必须将其从父容器中移除, 然后才能调用其 dispose 函数释放资源.
	 * @author StefanieKaka
	 */
	public final class KSpriteAnimator extends Sprite implements IKDispose, IKClonable
	{
		/**
		 * 构造函数, 
		 */
		public function KSpriteAnimator(bmpAnimator : KBitmapAnimator) 
		{
			m_bmpAnimator = bmpAnimator;
			this.addChild(m_bmpAnimator);
			
			this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStageHandler);
			this.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStageHandler);
			
			m_bmpAnimator.addEventListener(KAnimatorEvent.PLAY_END, onPlayEndHandler);
			m_bmpAnimator.addEventListener(KAnimatorEvent.UPDATE_FRAME, onUpdateFrameHandler);
			m_bmpAnimator.addEventListener(KAnimatorEvent.RENDER_FRAME, onRenderFrameHandler);
			
			m_anchorPoint = new Point();
			m_anchorPoint.x = m_anchorPoint.y = 0.5;
			
			play();
		}
		
///////////////////////////////////////////////////////////////////////////////////////////////////
// 公共域
///////////////////////////////////////////////////////////////////////////////////////////////////
		
		/**
		 * 继续播放动画, 从当前帧开始继续播放
		 */
		public function resume() : void
		{
			m_bmpAnimator.resume();
		}
		
		/**
		 * 暂停播放, 停止在当前帧
		 */
		public function pause() : void
		{
			m_bmpAnimator.pause();
		}
		
		/**
		 * 停止播放, 回到起始帧
		 */
		public function stop() : void
		{
			m_bmpAnimator.stop();
		}
		
		/**
		 * 从起始帧开始播放
		 * @param	repeatCount 播放次数, -1表示循环播放, 0表示播放一次, 1两次, 以此类推...
		 * @param	isPlayback 是否倒序播放, 默认顺序播放
		 */
		public function play(repeatCount : int = -1, isPlayback : Boolean = false) : void
		{
			m_bmpAnimator.play(repeatCount, isPlayback);
		}
		
		/**
		 * 跳到下一帧
		 */
		public function nextFrame() : void
		{
			m_bmpAnimator.nextFrame();
		}
		
		/**
		 * 跳回上一帧
		 */
		public function prevFrame() : void
		{
			m_bmpAnimator.prevFrame();
		}
		
		/**
		 * 跳到指定帧并且播放
		 * @param	frame 跳到的指定帧, 帧计数从 0 开始
		 * @param	repeatCount 播放次数, -1表示循环播放, 0表示播放一次, 1两次, 以此类推...
		 * @param	isPlayback 播放方式
		 */
		public function gotoAndPlay(frame : int, repeatCount : int = -1, isPlayback : Boolean = false) : void
		{
			m_bmpAnimator.gotoAndPlay(frame, repeatCount, isPlayback);
		}
		
		/**
		 * 跳到指定帧并且停止播放, 帧计数从 0 开始
		 * @param	frame 跳到的指定帧
		 */
		public function gotoAndStop(frame : int) : void
		{
			m_bmpAnimator.gotoAndStop(frame);
		}
		
		/// 获得当前帧, 帧计数从 0 开始
		public function getCurrentFrame() : int
		{
			return m_bmpAnimator.getCurrentFrame();
		}
		
		/// 获得总帧数
		public function getTotalFrame() : int
		{
			return m_bmpAnimator.getTotalFrame();
		}
		
		/// 获得重复播放次数
		public function getRepeatCount() : int
		{
			return m_bmpAnimator.getRepeatCount();
		}
		
		/// 获得动画是否播放结束
		public function isFinished() : Boolean
		{
			return m_bmpAnimator.isFinished();
		}
		
		/// 获得是否还在播放
		public function isPlaying() : Boolean
		{
			return m_bmpAnimator.isPlaying();
		}
		
		/// 获得是否倒序播放
		public function isPlayback() : Boolean
		{
			return m_bmpAnimator.isPlayback();
		}
		
		/// 是否实现平滑处理, 抗锯齿
		public function get smoothing() : Boolean
		{
			return m_bmpAnimator.smoothing;
		}
		
		public function set smoothing(value : Boolean) : void
		{
			m_bmpAnimator.smoothing = value;
		}
		
		/**
		 * 一次性播放, 播放结束后, 自动销毁
		 */
		public function get disposable() : Boolean
		{
			return m_disposable;
		}
		
		public function set disposable(value : Boolean) : void
		{
			m_disposable = value;
		}
		
		/**
		 * 每帧间隔时间
		 */
		public function get duration() : Number
		{
			return m_bmpAnimator.duration;
		}
		
		public function set duration(value : Number) : void
		{
			m_bmpAnimator.duration = value;
		}
		
		/**
		 * 设置定位点位置, anchorX 与 anchorY 的使用范围是 [0, 1].
		 * 0: 表示原始位图的坐标原点; 1: 表示原始位图的最大宽/高;
		 * 例如:
		 * 		(0, 0): 表示左上角;
		 * 		(1, 0): 表示右上角;
		 * 		(0, 1): 表示左下角;
		 * 		(1, 1): 表示右下角;
		 * @param	anchorX 定位点的 x 轴位置
		 * @param	anchorY 定位点的 y 轴位置
		 */
		public function setAnchorPoint(anchorX : Number, anchorY : Number) : void
		{
			if (anchorX < 0 || anchorX > 1 || anchorY < 0 || anchorY > 1)
				throw new ArgumentError("KSpriteAnimator.setAnchorPoint 提供的参数范围应在 [0, 1]");
			
			m_anchorPoint.x = anchorX;
			m_anchorPoint.y = anchorY;
			
			// 要求重新调整动画的位置
			m_bmpAnimator.dispatchEvent(new KAnimatorEvent(KAnimatorEvent.RENDER_FRAME, m_bmpAnimator.getCurrentFrame()));
		}
		
///////////////////////////////////////////////////////////////////////////////////////////////////
// 实现 IDispose
///////////////////////////////////////////////////////////////////////////////////////////////////
		
		/**
		 * 手动调用, 释放资源
		 */
		public function dispose() : void
		{
			if (m_isDisposed)
				return;
			m_isDisposed = true;
			
			this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStageHandler);
			this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStageHandler);
			m_bmpAnimator.removeEventListener(KAnimatorEvent.PLAY_END, onPlayEndHandler);
			m_bmpAnimator.removeEventListener(KAnimatorEvent.UPDATE_FRAME, onUpdateFrameHandler);
			m_bmpAnimator.removeEventListener(KAnimatorEvent.RENDER_FRAME, onRenderFrameHandler);
			m_bmpAnimator.dispose();
			m_bmpAnimator = null;
			
			Helper.removeChildren(this);
		}
		
///////////////////////////////////////////////////////////////////////////////////////////////////
// 实现 IKClonable
///////////////////////////////////////////////////////////////////////////////////////////////////
		
		/**
		 * 生成克隆动画
		 * @return KSpriteAnimator 需要强制类型转换
		 */
		public function clone() : IKClonable
		{
			return new KSpriteAnimator(m_bmpAnimator.clone() as KBitmapAnimator);
		}
		
///////////////////////////////////////////////////////////////////////////////////////////////////
// 私有域
///////////////////////////////////////////////////////////////////////////////////////////////////
		
		/// 添加到舞台事件
		private function onAddedToStageHandler(evt : Event) : void
		{
			// 动画更新优先级高于逻辑更新优先级
			this.stage.addEventListener(Event.ENTER_FRAME, onStageEnterFrameHandler, false, 0x02, false);
		}
		
		/// 从舞台移除事件
		private function onRemovedFromStageHandler(evt : Event) : void
		{
			this.stage.removeEventListener(Event.ENTER_FRAME, onStageEnterFrameHandler);
		}

		/// 渲染每帧
		private function onStageEnterFrameHandler(evt : Event) : void
		{
			m_bmpAnimator.update();
		}
		
		/// 播放结束事件
		private function onPlayEndHandler(evt : KAnimatorEvent) : void
		{
			this.dispatchEvent(evt);
			
			// 如果是一次性的动画, 那么播放结束后将释放资源, 并且自己从父容器中移除
			if (m_disposable)
			{
				if (this.parent != null)
					this.parent.removeChild(this);
				
				dispose();
			}
		}
		
		/// 更新帧事件
		private function onUpdateFrameHandler(evt : KAnimatorEvent) : void
		{
			this.dispatchEvent(evt);
		}
		
		/// 渲染新的帧事件
		private function onRenderFrameHandler(evt : KAnimatorEvent) : void
		{
			var frameInfo : KFrameInfo = m_bmpAnimator.getDisplayFrame(evt.renderFrame);	// 这是当前正在渲染的帧
			
			// 获得相对原始位图大小的偏移量
			var offset : Point = new Point(-frameInfo.sourceSize.x * m_anchorPoint.x,
											-frameInfo.sourceSize.y * m_anchorPoint.y);
											
			// 计算裁剪位图的偏移量
			offset.x += frameInfo.sourceRect.x;
			offset.y += frameInfo.sourceRect.y;
			m_bmpAnimator.x = offset.x;
			m_bmpAnimator.y = offset.y;
		}
		
		private var m_isDisposed : Boolean = false;
		private var m_bmpAnimator : KBitmapAnimator = null;
		private var m_disposable : Boolean = false;
		private var m_anchorPoint : Point = null;
	}

}

































///////////////////////////////////////////////////////////////////////////////////////////////////
// end file


